package com.kczyjg.hybird;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Looper;
import android.view.Surface;

/**
 * 设备旋转管理器
 */
public class RotationManager {

    private SensorManager mSensorManager;
    private Sensor mAccelerometer, mMageneticField;
    private float[] mValues = new float[3];
    private float[] mGravity = new float[3];
    private float[] mGeomagnetic = new float[3];
    private float[] mRotate = new float[9];
    private int mAccuracyValue;
    private float[] temporaryRotationMatrix = new float[9];
    private MySensorEventListener mMySensorEventListener;
    private RotationListener mRotationListener;
    private Handler mHandler;
    private static int DEFAULT_TIME = 300;
    private Context mContext;
    private Type type = Type.COMPASS;
    //设备旋转方向，用于确定横竖屏
    private int deviceOrientation = 0;

    public RotationManager(Context context) {
        this.mContext = context;
        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMageneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mMySensorEventListener = new MySensorEventListener();
        mHandler = new Handler(Looper.getMainLooper());
    }

    public RotationListener getRotationListener() {
        return mRotationListener;
    }

    public void setRotationListener(RotationListener rotationListener) {
        this.mRotationListener = rotationListener;
    }

    public void setType(Type type) {
        this.type = type;
    }

    /**
     * 判断是否有方向传感器
     *
     * @param context
     * @return
     */
    public static boolean hasOrientationSensor(Context context) {
        SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        Sensor mageneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        if (accelerometer == null || mageneticField == null) {
            return false;
        } else {
            return true;
        }
    }

    public void start() {
        //开启前先移除旧的监听
        cancel();
        mSensorManager.registerListener(mMySensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
        mSensorManager.registerListener(mMySensorEventListener, mMageneticField, SensorManager.SENSOR_DELAY_GAME);
        mHandler.postDelayed(mMySensorEventListener, DEFAULT_TIME);
    }

    public void cancel() {
        mSensorManager.unregisterListener(mMySensorEventListener, mAccelerometer);
        mSensorManager.unregisterListener(mMySensorEventListener, mMageneticField);
        mHandler.removeCallbacks(mMySensorEventListener);
    }

    private class MySensorEventListener implements SensorEventListener, Runnable {

        /**
         * 当传感器事件（SensorEvent）有更新时调用，如
         * 传感器的值 values
         * 传感器值的精度 accuracy
         * 传感器值的时间戳 timestamp
         *
         * @param event
         */
        @Override
        public void onSensorChanged(SensorEvent event) {
            int sensorType = event.sensor.getType();
            //不需要进行拷贝，直接使用传感器返回的数组进行计算就可以了
            if (sensorType == Sensor.TYPE_ACCELEROMETER) {
                System.arraycopy(event.values, 0, mGravity, 0, mGravity.length);
                orientationDevice(event.values.clone());
            }
            if (sensorType == Sensor.TYPE_MAGNETIC_FIELD) {
                System.arraycopy(event.values, 0, mGeomagnetic, 0, mGeomagnetic.length);
            }
            switch (type) {
                case CAMERA:
                    //利用加速度和磁场的传感器返回值，计算旋转举证
                    SensorManager.getRotationMatrix(temporaryRotationMatrix, null, mGravity, mGeomagnetic);
                    //转换坐标系
                    SensorManager.remapCoordinateSystem(temporaryRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, mRotate);
                    SensorManager.getOrientation(mRotate, mValues);
                    break;
                case COMPASS:
                    if (mContext instanceof Activity) {
                        Activity activity = (Activity) mContext;
                        if (activity.getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_90) {
                            SensorManager.getRotationMatrix(temporaryRotationMatrix, null, mGravity, mGeomagnetic);
                            SensorManager.remapCoordinateSystem(temporaryRotationMatrix, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, mRotate);
                            SensorManager.getOrientation(mRotate, mValues);
                            break;
                        }
                    }
                default:
                    SensorManager.getRotationMatrix(temporaryRotationMatrix, null, mGravity, mGeomagnetic);
                    SensorManager.getOrientation(temporaryRotationMatrix, mValues);
            }


        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            mAccuracyValue = accuracy;
        }

        @Override
        public void run() {
            if (mRotationListener != null) {
                mRotationListener.onRotationChanged((float) Math.toDegrees(mValues[0]),
                        (float) Math.toDegrees(mValues[1]), 0, mAccuracyValue, (float) Math.toDegrees(mValues[2]));
            }
            mHandler.postDelayed(this, DEFAULT_TIME);
        }
    }

    /**
     * 计算设备横竖屏方向，非拍摄相机朝向
     */
    private void orientationDevice(float[] values) {
        int orientation = -1;
        float X = -values[0];
        float Y = -values[1];
        float Z = -values[2];
        float magnitude = X * X + Y * Y;
        // Don't trust the angle if the magnitude is small compared to the y value
        if (magnitude * 4 >= Z * Z) {
            float OneEightyOverPi = 57.29577957855f;
            //Math.atan2(-Y, X) 是计算从原点(0,0)到(x,y)点的线段与x轴正方向之间的平面角度(弧度值)
            //得到的是原点(0,0)到(x,y)点的线段与x轴正方向之间的角度
            float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;
            //设备旋转的角度
            orientation = 90 - (int) Math.round(angle);
            // normalize to 0 - 359 range
            while (orientation >= 360) {
                orientation -= 360;
            }
            while (orientation < 0) {
                orientation += 360;
            }
        }
        deviceOrientation = orientation;
        /*if (orientation > 45 && orientation < 135) {
            //横屏翻转
        } else if (orientation > 135 && orientation < 225) {
            //竖屏翻转
        } else if (orientation > 225 && orientation < 315) {
            //横屏
        } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) {
            //竖屏
        }*/
    }

    public int getDeviceOrientation() {
        return deviceOrientation;
    }

    public interface RotationListener {
        void onRotationChanged(float yaw, float pitch, float roll, int accuracy, float rollReal);
    }

    public enum Type {

        CAMERA(1), COMPASS(2);

        private int value;

        Type(int value) {
            this.value = value;
        }

        public int getValue() {
            return this.value;
        }

    }
}
